package com.mlog.njyjy.ndop.monitor.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mlog.njyjy.ndop.monitor.dao.entity.TMonitorHost;
import com.mlog.njyjy.ndop.monitor.dao.entity.TMonitorHostGroup;
import com.mlog.njyjy.ndop.monitor.dao.entity.TMonitorHostItem;
import com.mlog.njyjy.ndop.monitor.dao.service.impl.TMonitorHostGroupServiceImpl;
import com.mlog.njyjy.ndop.monitor.dao.service.impl.TMonitorHostItemServiceImpl;
import com.mlog.njyjy.ndop.monitor.dao.service.impl.TMonitorHostServiceImpl;
import com.mlog.njyjy.ndop.monitor.dao.service.impl.TblSysContactPersonServiceImpl;
import com.mlog.njyjy.ndop.monitor.pojo.EventVO;
import com.mlog.njyjy.ndop.monitor.pojo.ItemKey;
import com.mlog.njyjy.ndop.share.zabbix.entity.ZabbixItem;
import com.mlog.njyjy.ndop.share.zabbix.method.ZabbixEventMethod;
import com.mlog.njyjy.ndop.share.zabbix.method.ZabbixHistoryMethod;
import com.mlog.njyjy.ndop.share.zabbix.method.ZabbixItemMethod;
import com.mlog.njyjy.ndop.share.zabbix.response.ZabbixResponseEvent;
import com.mlog.njyjy.ndop.share.zabbix.response.ZabbixResponseHistory;
import com.mlog.njyjy.ndop.share.zabbix.response.ZabbixResponseHost;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

@Service
public class ZabbixMonitorService {

	@Autowired
	private TMonitorHostServiceImpl hostServ;

	@Autowired
	private TMonitorHostGroupServiceImpl groupServ;

	@Autowired
	private TMonitorHostItemServiceImpl itemServ;

	@Autowired
	private TblSysContactPersonServiceImpl userServ;

	public List<TMonitorHost> listHosts() {
		return hostServ.list();
	}

	public JSONObject listHostsByGroup(String groupid) {
		JSONObject ret = new JSONObject();
		List<TMonitorHost> hosts = hostServ.list(new QueryWrapper<TMonitorHost>().eq("groupid", groupid));
		ret.put("hosts", hosts);
		int follows = 0, size = 0;
		if (hosts != null && hosts.size() > 0) {
			size = hosts.size();
			follows += hosts.stream().filter(host -> host.getFollow()).count();
		}
		ret.put("follows", follows);
		ret.put("size", size);
		return ret;
	}

	public JSONObject listHostGroups() {
		JSONObject ret = new JSONObject();
		List<TMonitorHostGroup> groups = groupServ.list(new QueryWrapper<TMonitorHostGroup>().eq("follow", 1));
		ret.put("groups", groups);
		int follows = 0, size = 0;
		if (groups != null && groups.size() > 0) {
			size = groups.size();
			follows += groups.stream().filter(group -> group.isFollow()).count();
		}
		ret.put("follows", follows);
		ret.put("size", size);
		return ret;
	}

	public JSONObject getHostInfo(String hostId) {
		TMonitorHost host = hostServ.getById(hostId);
		if(host == null)
			return null;
		List<ZabbixItem> os = ZabbixItemMethod.queryItemsByHost(hostId, ItemKey.SYSTEM_INFO);
		if (os.isEmpty())
			return null;
		String osname = os.get(0).getLastvalue();
		JSONObject ret = new JSONObject();
		ret.put("host", host);
		List<ZabbixItem> items = ZabbixItemMethod.queryItemsByHost(hostId, null);
		if (osname.toLowerCase().contains("windows")) {
			for (ZabbixItem item : items) {
				String key = item.getKey_();
				String value = item.getLastvalue();

				if (ItemKey.WINDOWS_MEMORY_FREE.equals(key))
					ret.put("memory_free", String.format("%.1f", Double.valueOf(value) / 1024 / 1024 / 1024) + "GB");
				if (ItemKey.WINDOWS_MEMORY_TOTAL.equals(key))
					ret.put("memory_total", String.format("%.1f", Double.valueOf(value) / 1024 / 1024 / 1024) + "GB");
				if (ItemKey.WINDOWS_CPU_USAGE.equals(key))
					ret.put("cpu_usage", String.format("%.1f", Double.valueOf(value)) + "%");
				if (ItemKey.WINDOWS_DISK_PFREE.equals(key))
					ret.put("disk_usage", String.format("%.1f", Double.valueOf(value)) + "%");
				if (ItemKey.WINDOWS_DISK_FREE.equals(key))
					ret.put("disk_free", String.format("%.1f", Double.valueOf(value) / 1024 / 1024 / 1024) + "GB");
				if (ItemKey.WINDOWS_DISK_TOTAL.equals(key))
					ret.put("disk_total", String.format("%.1f", Double.valueOf(value) / 1024 / 1024 / 1024) + "GB");
			}
		} else {
			for (ZabbixItem item : items) {
				String key = item.getKey_();
				String value = item.getLastvalue();
				if (ItemKey.LINUX_MEMORY_FREE.equals(key))
					ret.put("memory_free", String.format("%.1f", Double.valueOf(value) / 1024 / 1024 / 1024) + "GB");
				if (ItemKey.LINUX_MEMORY_TOTAL.equals(key))
					ret.put("memory_total", String.format("%.1f", Double.valueOf(value) / 1024 / 1024 / 1024) + "GB");
				if (ItemKey.LINUX_CPU_USAGE.equals(key))
					ret.put("cpu_usage", String.format("%.1f", Double.valueOf(value)) + "%");
				if (ItemKey.LINUX_DISK_PFREE.equals(key))
					ret.put("disk_usage", String.format("%.1f", 100 - Double.valueOf(value)) + "%");
				if (ItemKey.LINUX_DISK_FREE.equals(key))
					ret.put("disk_free", String.format("%.1f", Double.valueOf(value) / 1024 / 1024 / 1024) + "GB");
				if (ItemKey.LINUX_DISK_TOTAL.equals(key))
					ret.put("disk_total", String.format("%.1f", Double.valueOf(value) / 1024 / 1024 / 1024) + "GB");
			}
		}
		return ret;
	}

	public void setHost(List<TMonitorHost> hosts) {
		hostServ.saveOrUpdateBatch(hosts);
	}

	public void setHostGroup(List<TMonitorHostGroup> groups) {
		groupServ.saveOrUpdateBatch(groups);
	}

	public JSONObject getEventView(String groupid) {
		List<String> hostlist = null, grouplist = null;
		if (!StrUtil.isEmpty(groupid))
			grouplist = Arrays.asList(groupid);
		int lv1No = 0, lv2No = 0, lv3No = 0, lv4No = 0, lv5No = 0, lv0No = 0, total = 0;
		Date end = new Date();
		Date begin = DateUtil.offsetHour(end, -12);
		List<ZabbixResponseEvent> events = ZabbixEventMethod.getEvent(begin, end, hostlist, grouplist);
		List<TMonitorHost> hosts = hostServ
				.list(new QueryWrapper<TMonitorHost>().eq("groupid", groupid).eq("follow", 1));
		Map<String, EventVO> cache = new HashMap<>();
		for (TMonitorHost host : hosts) {
			EventVO ev = new EventVO();
			ev.setHost(host.getHost());
			ev.setHostid(host.getHostid());
			ev.setHostname(host.getName());
			ev.setIp(host.getIp());
			ev.setAvailable(host.getAvailable());
			cache.put(host.getHostid(), ev);
		}
		for (ZabbixResponseEvent event : events) {
			ZabbixResponseHost host = event.getHosts().get(0);
			if (host == null)
				continue;
			if (!cache.containsKey(host.getHostid()))
				continue;
			EventVO ev = cache.get(host.getHostid());
			String severity = event.getSeverity();
			ev.autoAdd(severity);
			cache.put(ev.getHostid(), ev);
			switch (severity) {
			case "0":
				lv0No++;
				break;
			case "1":
				lv1No++;
				break;
			case "2":
				lv2No++;
				break;
			case "3":
				lv3No++;
				break;
			case "4":
				lv4No++;
				break;
			case "5":
				lv5No++;
				break;
			default:
				lv0No++;
				break;
			}
			total++;
		}
		JSONObject ret = new JSONObject();
		ret.put("total", total);
		ret.put("lv1No", lv1No);
		ret.put("lv2No", lv2No);
		ret.put("lv3No", lv3No);
		ret.put("lv4No", lv4No);
		ret.put("lv5No", lv5No);
		ret.put("lv0No", lv0No);
		ret.put("hosts", cache.values());
		return ret;
	}

	public JSONObject getEventList(Date begin, Date end, String keyWord, String groupids, String levels, String ack) {
		List<String> groupList = null, levellist = null;
		if (groupids != null)
			groupList = Arrays.asList(groupids.split(","));
		if (levels != null)
			levellist = Arrays.asList(levels.split(","));
		List<ZabbixResponseEvent> events = ZabbixEventMethod.getEvent(begin, end, null, groupList);
		JSONObject ret = new JSONObject();
		JSONArray eventArray = new JSONArray();
		for (ZabbixResponseEvent event : events) {
			ZabbixResponseHost host = event.getHosts().get(0);
			if (host == null)
				continue;
			String severity = event.getSeverity();
			if (levels != null && !levellist.contains(severity))
				continue;
			if (ack != null && !ack.equals(event.getAcknowledged()))
				continue;
			if (!StrUtil.isEmpty(keyWord.trim()) && (event.getDescription() == null && host.getName() == null))
				continue;
			if (!StrUtil.isEmpty(keyWord.trim())
					&& (!event.getDescription().contains(keyWord) && !host.getName().contains(keyWord)))
				continue;
			String hostid = host.getHostid();
			JSONObject eventObj = JSONUtil.parseObj(event);
			TMonitorHost dbhost = hostServ.getById(hostid);
			eventObj.put("maintainerName", userServ.getById(dbhost.getMaintainer()));
			eventArray.add(event);
		}
		ret.put("events", eventArray);
		ret.put("title", DateUtil.format(new Date(), "更新时间：yyyy/MM/dd HH:mm:ss"));
		return ret;
	}

	public JSONObject getEventListByHost(String hostid) {
		Date end = new Date();
		Date begin = DateUtil.offsetHour(end, -24);
		List<String> hostids = null;
		if (hostid != null)
			hostids = Arrays.asList(hostid.split(","));
		List<ZabbixResponseEvent> events = ZabbixEventMethod.getEvent(begin, end, hostids, null);
		JSONObject ret = new JSONObject();
		TMonitorHost dbhost = hostServ.getById(hostid);
		ret.put("events", events);
		ret.put("maintainer", userServ.getById(dbhost.getMaintainer()));
		ret.put("title", DateUtil.format(new Date(), "更新时间：yyyy/MM/dd HH:mm:ss"));
		return ret;
	}

	public JSONObject getHostLiveData(String hostid) {
		List<ZabbixItem> items = ZabbixItemMethod.queryItemsByHost(hostid, null);
		JSONObject ret = new JSONObject();
		JSONArray itemArray = new JSONArray();
		for (ZabbixItem item : items) {
			String key = item.getKey_();
			if (!InitService.ZABBIX_ITEM_ENUM.containsKey(key))
				continue;
			JSONObject itemobj = JSONUtil.parseObj(item);
			itemobj.put("description", InitService.ZABBIX_ITEM_ENUM.get(key).getDescZh());
			itemArray.add(itemobj);
		}
		ret.put("items", itemArray);
		return ret;
	}

	private boolean isWindows(String hostid) {
		TMonitorHost host = hostServ.getById(hostid);
		if (host.getUname() != null && host.getUname().toLowerCase().contains("windows"))
			return true;
		return false;
	}

	public JSONObject getTimeSeqData(String type, String hostid) {
		Date end = new Date();
		Date begin = DateUtil.offsetHour(end, -24);
		List<TMonitorHostItem> items = null;
		if ("cpu".equalsIgnoreCase(type)) {
			items = itemServ.list(new QueryWrapper<TMonitorHostItem>().eq("hostid", hostid).like("itemkey", "system.cpu.util%"));
		} else {
			items = itemServ.list(new QueryWrapper<TMonitorHostItem>().eq("hostid", hostid).like("itemkey", "vm.memory.size%"));
		}
		JSONObject ret = new JSONObject();
		JSONArray itemarray = new JSONArray();
		for(TMonitorHostItem item : items) {
			List<ZabbixResponseHistory> hisdata = ZabbixHistoryMethod.getHistory(item.getItemid(), begin, end, null);
			if (hisdata.isEmpty())
				return null;
			Double max = hisdata.stream().map(data -> data.getValue()).map(Double::parseDouble).max(Double::compareTo)
					.get();
			Double min = hisdata.stream().map(data -> data.getValue()).map(Double::parseDouble).min(Double::compareTo)
					.get();
			Double avg = hisdata.stream().map(data -> data.getValue()).map(Double::parseDouble)
					.collect(Collectors.averagingDouble(Double::doubleValue));
			JSONObject itemset = new JSONObject();
			List<ZabbixResponseHistory> sublist = new ArrayList<>();
			IntStream.range(0, hisdata.size()).forEach(i -> {
				if (i % 60 == 0)
					sublist.add(hisdata.get(i));
			});

			itemset.put("max", max);
			itemset.put("min", min);
			itemset.put("avg", avg);
			itemset.put("latest", hisdata.get(0).getValue());
			itemset.put("values", sublist);
			itemset.put("name", item.getName());
			itemarray.add(itemset);
		}
		ret.put("items", itemarray);
		return ret;
	}

	public JSONObject getFocusHosts(String groupid) {
		List<TMonitorHost> hosts = hostServ
				.list(new QueryWrapper<TMonitorHost>().eq("groupid", groupid).eq("focus", 1));
		if (hosts.isEmpty())
			return null;
		JSONArray arr = new JSONArray();
		hosts.forEach(host -> arr.add(getHostInfo(host.getHostid())));
		JSONObject ret = new JSONObject();
		ret.put("hosts", arr);
		return ret;
	}
}
